package com.csproj.system.service;

import com.csproj.siiat.security.CurrentUser;
import com.csproj.siiat.security.UserNotActivatedException;
import com.csproj.system.domain.AuthorityInfo;
import com.csproj.system.domain.UserInfo;
import com.csproj.system.repository.AuthorityInfoRepository;
import com.csproj.system.repository.UserInfoRepository;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.stream.Collectors;

@Component("userDetailsService")
public class LoginService implements UserDetailsService {

    private final Logger log = LoggerFactory.getLogger(LoginService.class);
    private final UserInfoRepository userInfoRepository;
    private final AuthorityInfoRepository authorityInfoRepository;

    public LoginService(UserInfoRepository userInfoRepository,
                        AuthorityInfoRepository authorityInfoRepository) {
        this.userInfoRepository = userInfoRepository;
        this.authorityInfoRepository = authorityInfoRepository;
    }


    @Override
    @Transactional
    public CurrentUser loadUserByUsername(final String login) {
        log.debug("Authenticating {}", login);
        String lowercaseLogin = login.toLowerCase(Locale.ENGLISH);
        Optional<UserInfo> userFromDatabase = Optional.of(userInfoRepository.findByAccount(lowercaseLogin));
        CurrentUser currentUser = userFromDatabase.map(user -> {

            if (!user.getUsedFlag()) {
                throw new UserNotActivatedException("unactivated");
            }
            List<AuthorityInfo> authorityInfoList = authorityInfoRepository.findByUserInfoId(user.getId());
            List<GrantedAuthority> grantedAuthorities = authorityInfoList.stream()
                    .map(authority -> new SimpleGrantedAuthority(StringUtils.isNotBlank(authority.getPermission())?authority.getPermission():"权限"))
                    .collect(Collectors.toList());
            grantedAuthorities.add(new SimpleGrantedAuthority("permission"));

            CurrentUser thisCurrentUser = new CurrentUser(login,user.getPassword(),grantedAuthorities);
            thisCurrentUser.setId(user.getId());
            thisCurrentUser.setName(user.getName());
            thisCurrentUser.setSitId(user.getSiteId());
            return thisCurrentUser;
        }).orElseThrow(() -> new UsernameNotFoundException("User " + lowercaseLogin + " was not found in the " +
                "database"));
        return currentUser;
    }
}
